package cn.sample.security.json.handler;

import cn.sample.common.properties.SysProperties;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <h2></h2>
 *
 * <p>JSON 自定义退出处理逻辑</p>
 *
 * @author HKD
 */
@Component
public class JsonLogoutHandler implements LogoutHandler {

    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    @Resource
    private SysProperties sysProperties;
    @Resource
    private JsonAuthenticationFailureHandler authenticationFailureHandler;

    @Override
    @SneakyThrows
    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        //获取请求头
        String headerToken = request.getHeader(HttpHeaders.AUTHORIZATION);

        if(StringUtils.isNoneBlank(headerToken)){
            String[] auths = headerToken.split(":");
            if(auths.length != 2){
                unsuccessfulAuthentication(request,response,new AccountExpiredException("请求异常。"));
                return;
            }
            String tokenCacheKey = StringUtils.join(sysProperties.getProject(),":security:auto:",auths[0],":",auths[1]);
            Long expire = redisTemplate.getExpire(tokenCacheKey);
            expire = expire == null ? 0L : expire;
            if(expire <= 0L){
                unsuccessfulAuthentication(request,response,new AccountExpiredException("登录已过期。"));
                return;
            }

            // 删除 token
            redisTemplate.delete(tokenCacheKey);

            SecurityContextHolder.clearContext();
        }else {
            unsuccessfulAuthentication(request,response,new AccountExpiredException("请先登录！"));
        }

    }

    /**
     * 验证失败处理
     */
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException exception) throws IOException, ServletException {
        this.authenticationFailureHandler.onAuthenticationFailure(request, response, exception);
    }
}
